package com.google.android.apps.wakemewhere.mapsearch;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Observable;
import java.util.logging.Logger;

import com.google.android.maps.GeoPoint;

import android.content.Context;

public class SearchResultAggregator extends Observable implements SearchResultProvider, SearchResultCallback {
	
	private Logger logger = Logger.getLogger(getClass().getName());

	private final List<SearchResultProvider> providers = new ArrayList<SearchResultProvider>();
	private final List<SearchResultProvider> finishedProviders = new ArrayList<SearchResultProvider>();
	private final List<SearchResult> resultsSoFar = new ArrayList<SearchResult>();
	private final SearchResultCallback callback;
	
	public SearchResultAggregator(Context context, SearchResultCallback callback) {
		providers.add(new PlaceSearch(context));
		providers.add(new BusinessSearch());
		this.callback = callback;
	}
	
	public void asyncSearch(String query, SearchResultCallback callback, Object tag, GeoPoint upperLeft, GeoPoint lowerRight) {
		for (SearchResultProvider provider : providers) {
			provider.asyncSearch(query, this, tag, upperLeft, lowerRight);
		}
	}

	public void onSearchResults(List<SearchResult> newResults, Object tag, SearchResultProvider provider, boolean finished) {
		logger.warning("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
		logger.warning("2 DEBUG::: provider " + provider + " has given back:");
		for (SearchResult result : newResults) {
			logger.warning("2 DEBUG:::::: result:" + result);
		}
		logger.warning("2 DEBUG::: Result count = " + newResults.size());
		
		if (finished) {
			finishedProviders.add(provider);
		}
		
		List<SearchResult> previousResultsSoFar = new ArrayList<SearchResult>(resultsSoFar);
		resultsSoFar.addAll(newResults);
		Collections.sort(resultsSoFar);
		deduplicate(resultsSoFar);
		
		if (!previousResultsSoFar.equals(resultsSoFar)) {
			callback.onSearchResults(resultsSoFar, tag, provider, isFinished());
		}
	}
	
	private boolean isFinished() {
		boolean finished = finishedProviders.containsAll(providers);
		logger.warning("isFinished returning " + finished);
		return finished;
	}
	
	@SuppressWarnings({ "rawtypes", "unchecked" })
	private static void deduplicate(List items) {
		HashSet set = new HashSet();
		set.addAll(items);
		items.clear();
		items.addAll(set);
	}

}
